technical_minecraftfandomcom-20200214-history
FallingSand
Some blocks in Minecraft are affected by gravity by default, such as gravel, sand, red sand, anvils, and dragon eggs. These blocks all share the same basic structure for dealing with their gravity. Many glitches exists and have existed with these kinds of blocks, most notably sand duplicators and metadata changers. Currently, sand generators are, for the most part, fixed. Generators have been made using only pistons, but the latest designs use TNT to push FallingSand entities through an end portal. Uses Using FallingSand entities you can use it for various tasks like invisible walls or just moving a block around visually. FallingSand entities can be changed using its NBT data which can change the look of the block to anything like in SimplySarcs video: https://www.youtube.com/watch?v=5M6lkQtNTwk Sand generators * FallingBlock duplication using end portals - https://www.youtube.com/watch?v=7m2G1QeV-nQ * Super fast sand generator - https://www.youtube.com/watch?v=QEvTBxEJWMw * Sand metadata changer - https://www.youtube.com/watch?v=ulh6-HvscTo Metadata changers When a FallingSand entity is created, the block and the entity coexist for a short while. In this time, another block may be pushed in, which then gets its metadata changed. See the commented code for a better explanation. The code Every time a BlockFalling is given a block update, it checks the block below it to determine whether it is allowed to fall or not. If the block is allowed to fall, it summons a FalingSand entity in the exact middle of itself, with the same data as itself. The FallingBlock entity is updated every tick, and the code is quite interesting, allowing for both metadata changers, and possibly sand duplicators. Bug theory ---------- Entity is created. The entity and the block coexist until the next tick. After the entity has been created, the block is pushed into it. The original sand block is pushed on. Entity is updated one tick later and deletes the sand block. It then proceeds to fall down and sets the block as its own color. Invisible block bug ----------- FallingSand summoned inside another block causes the block to disappear. Can also convert sand. Sand generators --------------- For 1 tick, the sand block and the entity coexists. We used to be able to use TNT to push the FallingSand into a portal. Pseudocode ---------- BlockFalling->Update: If canFallDown: SummonEntityFallingBlock(world, posX + 0.5, posY + 0.5, posZ + 0.5, BlockState(currentPosition)); SummonEntityFallingBlock(world, posX, posY, posZ, blockState): // More like original block state. this.blockState = blockState; this.preventEntitySpawning = true; this.setSize(0.98, 0.98); this.setPosition(posX, posY, posZ); this.motionX = this.motionY = this.motionZ = 0; this.prevPosX = posX; this.prevPosY = posY; this.prevPosZ = posZ; this.fallTime = 0; // Method called every tick. EntityFallingBlock->Update: block currentBlock = this.currentPosition.getBlock(); // If it currently is inside air, the entity gets killed. // This is probably a safety check of some sorts. If the original block is deleted, // the entity must not keep on falling, because that could result in a dupe/block deletion thing. if currentBlock.getMaterial() Material.air: this.setDead(); else: this.prevPosX = this.posX; this.prevPosY = this.posY; this.prevPosZ = this.posZ; // fallTime 0 is when the entity has not yet started falling. // The entity is not yet falling if it is pushed by a piston and then dropped. if this.fallTime 0: blockPos = new BlockPos(this); // If the FallingSand has not started falling, and it is currently inside the original block, // that block is deleted. This means that the FallingSand and original block were coexisting. // Unfortunately, the old fallTime check used to be set at 1 tick. Now, the sand generators // have been fixed and it is probably impossible to recover the original block or the entity. if this.world.getBlockState(blockPos).getBlock() currentBlock: this.setBlockToAir(blockPos); // If there is no block to be deleted, the FallingSand entity itself is deleted. // This was the initial fix for sand generators. else: this.setDead(); else: this.fallTime += 1; this.motionY -= 0.04; this.moveEntity(this.motionX, this.motionY, this.motionZ); this.motionX *= 0.98; this.motionY *= 0.98; this.motionZ *= 0.98; blockPos = new BlockPos(this); // I think any collision vertically triggers this.onGround, so it being inside the bounding box is enough for this to be triggered. // I do not think the bottom part needs to be inside the block, any part should work. if this.onGround: // Ensures that FallingSand may be pushed by pistons. if this.world.getBlockState(blockPos) != Blocks.pistonExtension: this.setDead(); // The game here sets the block in the position of the FallingBlock to be a block // with the state of the original block. The FallingSand entity only checks the type // of the block, and the state of the block does not need to match. This allows // for the metadata changing of FallingBlocks. // 1 - The entity is created. The entity and the block coexist until the next tick. // 2 - After the entity has been created, the block is pushed into it with a zero tick. // 3 - One tick later, the entity is updated. The entity deletes the original sand block. // It then proceeds to fall down and sets the block as its own color, having deleted // the sand block with the wrong metadata. if cannotContinueFalling && canBePlaced && this.world.setBlockState(blockPos, this.blockState, automaticBlockUpdate): saveData() else: this.drop() Category:Entities